from odoo import api, fields, models, _


class DocumentsDdtWizard(models.TransientModel):
    _name = "documents.ddt.wizard"
    _description = "DDT向导"

    language_mode = fields.Selection(
        selection=[("zh", "中文"), ("en", "英文"), ("it", "意大利文")],
        string="语言",
        default="zh",
        required=True,
    )
    export_format = fields.Selection(
        selection=[("xlsx", "XLSX")],
        string="导出格式",
        default="xlsx",
        required=True,
    )

    auto_number = fields.Char(
        string="编号",
        default=lambda self: self.env["ir.sequence"].next_by_code("mommy.documents.ddt"),
    )
    date = fields.Date(string="日期", default=fields.Date.context_today, required=True)
    company_id = fields.Many2one(
        comodel_name="res.company",
        string="公司",
        default=lambda self: self.env.company,
        required=True,
    )
    partner_id = fields.Many2one(
        comodel_name="res.partner",
        string="客户",
        domain=[("type", "!=", "private")],
    )

    package_ids = fields.Many2many(
        comodel_name="stock.quant.package",
        relation="documents_ddt_wizard_package_rel",
        column1="wizard_id",
        column2="package_id",
        string="包装",
        required=True,
    )

    detail_level = fields.Selection(
        selection=[("summary", "汇总"), ("detailed", "详细")],
        string="详细程度",
        default="detailed",
        required=True,
    )

    carrier_id = fields.Many2one(
        comodel_name="res.partner",
        string="承运商",
        domain=[("type", "!=", "private")],
    )
    transport_method = fields.Selection(
        selection=[
            ("sea", _("海运")),
            ("air", _("空运")),
        ],
        string="运输方式",
    )
    order_reference = fields.Char(string="订单参考")
    license_plate = fields.Char(string="车牌号")
    container_no = fields.Char(string="集装箱号")
    seal_no = fields.Char(string="封条号")
    pickup_date = fields.Date(string="提货/开始运输日期")
    departure_port = fields.Char(string="出发港口")
    destination_port = fields.Char(string="目的港口")
    net_weight = fields.Float(string="净重(公斤)")
    gross_weight = fields.Float(string="毛重(公斤)")

    note = fields.Text(string="备注")

    line_ids = fields.One2many(
        comodel_name="documents.ddt.wizard.line",
        inverse_name="wizard_id",
        string="明细行",
    )
    group_ids = fields.One2many(
        comodel_name="documents.ddt.wizard.group",
        inverse_name="wizard_id",
        string="分组",
    )

    # 生成的下载文件
    file_name = fields.Char(string="文件名", readonly=True)
    file_data = fields.Binary(string="文件", readonly=True)

    @api.onchange("company_id")
    def _onchange_company_id(self):
        if self.company_id and not self.partner_id:
            self.partner_id = self.company_id.partner_id

    @api.onchange("package_ids")
    def _onchange_package_ids(self):
        """根据选择的包装自动设置客户。

        通过跟踪 包装 -> 移动行 -> 拣货/客户 或相关移动的销售行上的销售订单来推断客户。
        """
        self.ensure_one()
        if not self.package_ids:
            return

        StockMoveLine = self.env["stock.move.line"]
        move_lines = StockMoveLine.search([
            "|",
            ("result_package_id", "in", self.package_ids.ids),
            ("package_id", "in", self.package_ids.ids),
        ])

        # 优先使用销售订单的客户；否则仅当拣货是“出库/发往客户”时才使用拣货上的 partner
        sale_partner_ids = set()
        customer_pick_partner_ids = set()
        for move_line in move_lines:
            # 来自销售订单的客户（最可靠）
            sale_partner = move_line.move_id.sale_line_id.order_id.partner_id
            if sale_partner:
                sale_partner_ids.add(sale_partner.id)

            # 仅当拣货类型为 outgoing 或目标库位为 customer 时，才认为其为客户
            picking = move_line.picking_id
            if picking and picking.partner_id:
                picking_type_code = getattr(getattr(picking, "picking_type_id", None), "code", False)
                dest_usage = getattr(getattr(picking, "location_dest_id", None), "usage", False)
                if picking_type_code == "outgoing" or dest_usage == "customer":
                    customer_pick_partner_ids.add(picking.partner_id.id)

        candidate_ids = sale_partner_ids or customer_pick_partner_ids
        if len(candidate_ids) == 1:
            self.partner_id = list(candidate_ids)[0]

    def action_export(self):
        self.ensure_one()
        if self.export_format == "xlsx":
            url = "/mommy_documents/ddt/%s/xlsx" % self.id
            return {
                "type": "ir.actions.act_url",
                "url": url,
                "target": "self",
            }
        return self.env.ref("gs_documents.action_report_ddt_pdf").report_action(self)

    def action_print_pdf(self):
        self.ensure_one()
        action = self.env.ref("gs_documents.action_report_ddt_pdf").report_action(self)
        return action

    def action_preview_pdf(self):
        return self.action_print_pdf()


class DocumentsDdtWizardLine(models.TransientModel):
    _name = "documents.ddt.wizard.line"
    _description = "DDT向导明细行"

    wizard_id = fields.Many2one(
        comodel_name="documents.ddt.wizard",
        string="DDT向导",
        required=True,
        ondelete="cascade",
    )
    
    sequence = fields.Integer(string="序号", default=10)
    product_id = fields.Many2one(
        comodel_name="product.product",
        string="产品",
        required=True,
    )
    product_code = fields.Char(string="产品编码")
    product_name = fields.Char(string="产品名称")
    quantity = fields.Float(string="数量", default=1.0)
    uom_id = fields.Many2one(
        comodel_name="uom.uom",
        string="单位",
    )
    package_id = fields.Many2one(
        comodel_name="stock.quant.package",
        string="包装",
    )
    lot_id = fields.Many2one(
        comodel_name="stock.lot",
        string="批次",
    )
    weight = fields.Float(string="重量")
    note = fields.Text(string="备注")


class DocumentsDdtWizardGroup(models.TransientModel):
    _name = "documents.ddt.wizard.group"
    _description = "DDT向导分组"

    wizard_id = fields.Many2one(
        comodel_name="documents.ddt.wizard",
        string="DDT向导",
        required=True,
        ondelete="cascade",
    )
    
    name = fields.Char(string="分组名称", required=True)
    sequence = fields.Integer(string="序号", default=10)
    line_ids = fields.Many2many(
        comodel_name="documents.ddt.wizard.line",
        relation="ddt_wizard_group_line_rel",
        column1="group_id",
        column2="line_id",
        string="明细行",
    )
    total_quantity = fields.Float(string="总数量", compute="_compute_totals")
    total_weight = fields.Float(string="总重量", compute="_compute_totals")
    
    @api.depends("line_ids.quantity", "line_ids.weight")
    def _compute_totals(self):
        for group in self:
            group.total_quantity = sum(group.line_ids.mapped("quantity"))
            group.total_weight = sum(group.line_ids.mapped("weight")) 